#include "pluginmanage.h"
#include <QFileInfo>
#include <QDir>
#include <QDebug>

PluginManage::PluginManage(QObject *parent) : QObject(parent)
{
    QDir pluginsDir(QDir::currentPath());
    pluginsDir.cd("plugins");
    mPluginDir = pluginsDir.path();
}

void PluginManage::setPluginRootPath(QString dir)
{
    mPluginDir = dir;
}
QString PluginManage::getPluginRootPath()
{
    return mPluginDir;
}
#include <QLibrary>
QStringList PluginManage::findPlugin(QString dir)
{
    QStringList fileList;
    QDir pluginsDir(dir);
    //查找当前目录下的文件
    QFileInfoList pluginsInfo = pluginsDir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot);
    for(QFileInfo fileinfo : pluginsInfo)
    {
        QString fileName = fileinfo.absoluteFilePath();
        if(QLibrary::isLibrary(fileName))  //如果是插件文件就加入
            fileList.append(fileName);
    }
    //递归目录
    QFileInfoList dirsInfo = pluginsDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
    for(QFileInfo dirInfo : dirsInfo)
    {
        QString dirName = dirInfo.absoluteFilePath() ;
        fileList.append(findPlugin(dirName));
    }

    return fileList;
}

//输入插件路径，拷贝到本地plugins目录下，并加入到插件系统
bool PluginManage::addPlugin(const QString &filePath)
{
    QFile pluginFile(filePath);
    if(!pluginFile.exists())
        return 0;
    //拷贝复制
    pluginFile.copy(mPluginDir + "/" + pluginFile.fileName());
    //还需要加载插件，如果加载不了还需要删除插件文件
    return 1;
}

bool PluginManage::removePlugin(const QString &filePath)
{
    QFile pluginFile(filePath);
    if(!pluginFile.remove())
        return 0;
    //还需要卸载插件
    return 1;
}

bool PluginManage::removeAllPlugin()
{
    QDir pluginsDir(mPluginDir);
    QFileInfoList pluginsInfo = pluginsDir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot);

    for(QFileInfo fileinfo : pluginsInfo)
        QFile::remove(fileinfo.absoluteFilePath());

    //判断是否清空
    pluginsInfo = pluginsDir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot);
    return pluginsInfo.isEmpty();
}

void PluginManage::loadAllPlugin()
{
    QStringList pluginFiles = findPlugin(mPluginDir);
    for(QString file : pluginFiles)
        loadPlugin(file);
}

#include <QLibrary>
#include <QPluginLoader>
bool PluginManage::loadPlugin(const QString &filePath)
{
    if(!QLibrary::isLibrary(filePath))
        return 0;

    QPluginLoader loader(filePath);
    if(loader.load())
    {
        PluginInterface *plugin = qobject_cast<PluginInterface *>(loader.instance());
        if(plugin)
        {
            plugin->setConfig(filePath);
            mPluginHash.insert(filePath,plugin);
            emit sigLoadPlugin(plugin);
            qDebug()<<Q_FUNC_INFO<<"插件加载成功，路劲："<<filePath<<"   插件名字："<<plugin->getName();
            return 1;
        }
        else
            qDebug()<<Q_FUNC_INFO<<"插件加载失败，路劲："<<filePath<<"   插件实例化失败！";
    }
    else
        qDebug()<<Q_FUNC_INFO<<"插件加载失败，路劲："<<filePath<<"   错误信息："<<loader.errorString();
    return 0;
}

void PluginManage::unloadAllPlugin()
{
    QStringList pluginFiles = mPluginHash.keys();
    for(QString file : pluginFiles)
        unloadPluin(file);
}

bool PluginManage::unloadPluin(const QString &filePath)
{
    if(!isLoaded(filePath))
    {
        qDebug()<<Q_FUNC_INFO<<"插件卸载失败，路劲："<<filePath<<"   插件未被加载！";
        return 0;
    }
    QPluginLoader loader(filePath);
    //卸载插件，并从内部数据结构中移除
    if(loader.unload())
    {
        //emit sigLoadPlugin(plugin);
        mPluginHash.remove(filePath);
        qDebug()<<Q_FUNC_INFO<<"插件卸载成功，路劲："<<filePath;
        return 1;
    }
    qDebug()<<Q_FUNC_INFO<<"插件卸载失败，路劲："<<filePath<<"   错误信息："<<loader.errorString();
    return 0;
}

bool PluginManage::isLoaded(const QString &filePath)
{
    return mPluginHash.contains(filePath);
}

PluginInterface *PluginManage::getPlugin(const QString &filePath)
{
    return mPluginHash.value(filePath);
}

QHash<QString, PluginInterface *> PluginManage::getAllPlugin()
{
    return mPluginHash;
}
